// FlyingOBJ.cpp: implementation of the FlyingOBJ class.
//
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <mmsystem.h>
#include <objbase.h>
#include <malloc.h> // _alloca
#include <stdio.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9.h>
#include <D3D9.h>
#include "dxutil.h"
#include "d3dutil.h"
#include "d3dfont.h"
#include "D3DEnumeration.h"
#include "DXUtil.h"
#include "D3DEnumeration.h"
#include "D3DSettings.h"
#include "Anicontainer.h"
#include "d3dutil.h"
#include <d3dmodel.h>
#include <D3dAddon.h>
#include "ToolApp.h"
#include "FlyingOBJ.h"


extern D3DModel *GetModel();
extern ToolApp *g_Draw;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//extern OUTMODELMESH modelmeshlist[];
//extern int nmodellist;
D3DXVECTOR3 Bezier3(D3DXVECTOR3 p1,D3DXVECTOR3 p2,D3DXVECTOR3 p3,float mu)
{
   float mum1,mum12,mu2;
   D3DXVECTOR3 p;

   mu2 = mu * mu;
   mum1 = 1 - mu;
   mum12 = mum1 * mum1;
   p.x = p1.x * mum12 + 2 * p2.x * mum1 * mu + p3.x * mu2;
   p.y = p1.y * mum12 + 2 * p2.y * mum1 * mu + p3.y * mu2;
   p.z = p1.z * mum12 + 2 * p2.z * mum1 * mu + p3.z * mu2;

   return(p);
}
void GetDirectionMatrix3(D3DXVECTOR3 start,D3DXVECTOR3 des,D3DXMATRIX &mat)
{
	D3DXVECTOR3 up(0.0f,1.0f,0.0f);
	D3DXVECTOR3 xdir;
	D3DXVECTOR3 ydir;
	D3DXVECTOR3 zdir;
//	des=start-des;
	des=des-start;
	if (des.x==0.0f && des.y==0.0f && des.z==0.0f )
	{
		D3DXMatrixIdentity(&mat);
		return;
	}
	D3DXVec3Normalize(&zdir,&des);
//	D3DXVec3Cross(&xdir,&up,&start);
	D3DXVec3Cross(&xdir,&zdir,&up);
	D3DXVec3Normalize(&xdir,&xdir);
	D3DXVec3Cross(&ydir,&xdir,&zdir);
	D3DXVec3Normalize(&ydir,&ydir);
	mat._11=xdir.x;
	mat._12=xdir.y;
	mat._13=xdir.z;
	mat._31=ydir.x;
	mat._32=ydir.y;
	mat._33=ydir.z;
	mat._21=zdir.x;
	mat._22=zdir.y;
	mat._23=zdir.z;
/*	mat._11=xdir.x;
	mat._12=xdir.y;
	mat._13=xdir.z;
	mat._21=ydir.x;
	mat._22=ydir.y;
	mat._23=ydir.z;
	mat._31=zdir.x;
	mat._32=zdir.y;
	mat._33=zdir.z;*/
}

FlyingOBJ *flylist[100]={NULL,};
FlyingOBJ::FlyingOBJ(D3DXMATRIX _start,DWORD tid,AddOnContainer *me,void *element)
{
	for (int i=0;i<100;i++)
	{
		if (!flylist[i])
		{
			flylist[i]=this;
			flyid=i;
			break;
		}
	}
	lefthand=((SDrawElement *)element)->FindFrame(  ((BoneMesh*)((SDrawElement *)element)->Weapon)->parentname );
	ele=element;
	iscrash=FALSE;
	start.x=_start._41;
	start.y=_start._42;
	start.z=_start._43;
	targetid=tid;
	mesh=me;
	targetheight=6.0f+( (float(   (rand() % 16)-8))/4.0f);
	flyingheight=4.5f+( (float(   (rand() % 16)-8))/8.0f);
//	if (targetid!=0xffff && ObjectList[targetid] && (ObjectList[targetid]->ClassID==ID_PC1 || ObjectList[targetid]->ClassID==ID_NPC1))
	{
//				D3DXMATRIX *pos=(D3DXMATRIX *)OBJECT::ObjectList[targetid]->ObjProc(OM_GETPOSMATRIX,0,0);
				target.x=0;
				target.y=5;
				target.z=-40;
	}
	D3DXMatrixIdentity(&pos);
	GetDirectionMatrix3(start,target,pos);
	remaintime=5.0f;
	isremain=FALSE;
	status=FLY_ONHAND;
//	DisplayLevel=TERRAIN_LEVEL;
	factor=0.0f;
	oldlen=0.0f;
	len=0.0f;

}
FlyingOBJ::FlyingOBJ()
{
//	D3DXMatrixIdentity(&pos);
	D3DXMatrixRotationX(&pos,3.141592/2);
	factor=0.0f;
	oldlen=0.0f;
	len=0.0f;
}

FlyingOBJ::~FlyingOBJ()
{
	flylist[flyid]=NULL;
}

INT FlyingOBJ::ObjProc(LONG hMsg, LONG wParam, LONG lParam)
{
	D3DXVECTOR3 newpos;
	SDrawElement *element=(SDrawElement *)ele;
	switch(hMsg)
	{
	case OM_TIMER:
		/*
		if (isremain)
		{
			if (targetid!=0xffff && ObjectList[targetid] && (ObjectList[targetid]->ClassID==ID_PC1 || ObjectList[targetid]->ClassID==ID_NPC1))
			{
						remaintime-=g_Draw.m_fElapsedTime;
						if (remaintime<=0.0f)
						{
							remaintime=0.0f;
//							MESSAGEMNG::SendMessage(this,OM_DESTROY,0,0);
						}
			}
			else
			{
							MESSAGEMNG::SendMessage(this,OM_DESTROY,0,0);
			}
			break;
		}*/
		/*
		if (targetid!=0xffff && ObjectList[targetid] && (ObjectList[targetid]->ClassID==ID_PC1 || ObjectList[targetid]->ClassID==ID_NPC1))
		{

				D3DXMATRIX *_pos=(D3DXMATRIX *)OBJECT::ObjectList[targetid]->ObjProc(OM_GETPOSMATRIX,0,0);
				target.x=_pos->_41;
				target.y=_pos->_42+targetheight;
				target.z=_pos->_43;
		}
		*/
		if (status==FLY_ONHAND)
		{
				pos=((SDrawElement *)ele)->matCombined[((SDrawElement *)ele)->pframeAddon->boneid];
				if ( element->attr.nhit && element->attr.hitPoint[0].start <=element->fCurTime)status=FLY_LOADED;
		}
		else if (status==FLY_LOADED)
		{
			D3DXVECTOR3 st,en;
			st.x= element->matTrans._41;
			st.y= element->matTrans._42;
			st.z= element->matTrans._43;
			en.x= element->matCombined[((SFrame *)lefthand)->boneid]._41;
			en.y= element->matCombined[((SFrame *)lefthand)->boneid]._42;
			en.z= element->matCombined[((SFrame *)lefthand)->boneid]._43;
			GetDirectionMatrix3(st,en,pos);
			pos._41 = element->matTrans._41;
			pos._42 = element->matTrans._42;
			pos._43 = element->matTrans._43;
			if (element->attr.hitPoint[0].end<=element->fCurTime)
			{
				start.x=pos._41;
				start.y=pos._42;
				start.z=pos._43;
//				flyingheight=en.y-st.y;
				status=FLY_FIRE;
			}
		}
		else
		{
		factor+=g_Draw->m_fElapsedTime*2.7f;
		oldpos.x=pos._41;
		oldpos.y=pos._42;
		oldpos.z=pos._43;
		Move(factor);
		newpos.x=pos._41;
		newpos.y=pos._42;
		newpos.z=pos._43;
		GetDirectionMatrix3(oldpos,newpos,pos);
		}
		if (factor>=1.0f)
		{
			factor=1.0f;
//			isremain=TRUE;
			delete this;
			break;
		}
		break;
	case OM_PAINT:
		Put();
		break;
	case OM_DESTROY:
		delete this;
		break;
	}
	return TRUE;
}

void FlyingOBJ::Put()
{
	if (!mesh)return;
	/*
	if (isremain)
	{
		if (targetid!=0xffff && ObjectList[targetid] && (ObjectList[targetid]->ClassID==ID_PC1 || ObjectList[targetid]->ClassID==ID_NPC1))
		{
			D3DXMATRIX invert;
				SDrawElement *ele=(SDrawElement *)OBJECT::ObjectList[targetid]->ObjProc(OM_GETELEMENT,0,0);
				if (!iscrash)
				{
							crash=pos;
							crash._41=crash._42=crash._43=0.0f;
							iscrash=TRUE;
				}

				npos=ele->pframeRoot->m_pBoneOffsetMat[ele->spineid]*crash;
				npos=npos*(*ele->m_pBoneMatrix[ele->spineid]);
				npos._41+=ele->matTrans._41;
				npos._42+=ele->matTrans._42;
				npos._43+=ele->matTrans._43;
				modelmeshlist[nmodellist].mesh=(AddOnContainer *)mesh;
				modelmeshlist[nmodellist].root=NULL;
				modelmeshlist[nmodellist++].mat=(D3DXMATRIX *)&npos;
		}
	}
	else
	{
		modelmeshlist[nmodellist].mesh=(AddOnContainer *)mesh;
		modelmeshlist[nmodellist].root=NULL;
		modelmeshlist[nmodellist++].mat=(D3DXMATRIX *)&pos;
	}
	*/
	GetAddon()->Render(mesh,pos);
}

void FlyingOBJ::Move(float _factor)
{
	D3DXVECTOR3 up(0,1,0);
	D3DXVECTOR3 midnorm(0,1,0);
	D3DXVECTOR3 mid;
	D3DXVECTOR3 xvec;
	mid=target-start;
	D3DXVec3Cross(&xvec,&up,&mid);
	D3DXVec3Cross(&midnorm,&mid,&xvec);
	D3DXVec3Normalize(&midnorm,&midnorm);
	len=D3DXVec3Length(&mid)/flyingheight;
	midnorm=midnorm*len;
	mid=(target-(target-start)/3)+midnorm;

	D3DXVECTOR3 cur;
	cur=Bezier3(start,mid,target,_factor);
	pos._41=cur.x;
	pos._42=cur.y;
	pos._43=cur.z;
}
